Using graphics processing units to render three-dimensional objects typically involves writing computer programs called “shaders.” A three-dimensional object typically is defined by a mesh, which is defined as a set of vertices and edges among those vertices. The set of edges and vertices define faces, where each face typically is a triangle, but may in some cases be some other polygon, or even nonplanar.
A common programming language for writing shaders is the OpenGL Shader Language (“GLSL”), which is is a high level shading language based on the C programming language. GLSL provides for, in general, two primary types of shaders: vertex shaders and fragment shaders.
According to the OpenGL Shading Language specification, language version 1.20, document version 8, dated Sep. 7, 2006, a vertex shader is written to run on a vertex processor in an OpenGL pipeline. The vertex processor is a programmable unit that operates on incoming vertices and their associated data. The vertex processor operates on one vertex at a time. It does not replace graphics operations that require knowledge of several vertices at a time. A fragment shader is written to run on a fragment processor in an OpenGL pipeline. The fragment processor is a programmable unit that operates on fragment values and their associated data. A fragment shader cannot change a fragment's x/y position. Access to neighboring fragments is not allowed. The values computed by the fragment shader are ultimately used to update frame-buffer memory or texture memory, depending on the current OpenGL state and the OpenGL command that caused the fragments to be generated.
In GLSL, a kind of variable, called a “varying,” provides the interface between the vertex shaders and the fragment shaders. Vertex shaders compute values per vertex and write them to variables declared with the varying qualifier. By definition, varying variables are set per vertex and are interpolated in a perspective-correct manner over the primitive being rendered. A fragment shader may read from varying variables and the value read will be the interpolated value, as a function of the fragment's position within the primitive. For example, if each vertex of a triangle has a different color associated with it, then the fragment shader, when applied to a fragment of that triangle, would receive an interpolated color value, based on the position of that fragment within the triangle.